﻿using SuperX.Common.Log;
using SuperX.ProjectCore;
using SuperX.ProjectManager;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Timers;

namespace IoTServiceCore
{
    public class Program
    {
        internal static object obj = new object();
        protected static Thread HostedThread { get; set; }
        private static HostedService _HostedService;
        private static System.Timers.Timer _timer;
        private static string k = "PYQSAEfKGPlbRn43aWxgf5KKVBu/k7+2bUDJTArIXVo5w1Ti0KslO6QljfYWVkhD/hU8igXzgS1asmsTf+YlmWwNEZ7qx1m3k7ylRIXmZ50z/Yr0gQY+JFCGmZo6Z0O1R+qhgPYO7PPTD8A7F1ueNYRtaM00VWV0k/v7L4nQwRg=";
        private static int _stopped;

        private static void Main(string[] args)
        {
            //启动日志记录程序
            if (!HslCommunication.Authorization.SetAuthorizationCode("6877ef20-7031-42d2-b5fd-5958a5de9fb5"))
            {
                Logger.Error("active failed");
            }
            else
            {
                Logger.Info("active success");
            }
            SetWorkDirectory();
            SuperX.Common.Log.Logger.Info(string.Format("{0}启动", AppDomain.CurrentDomain.FriendlyName));
            //获取是否有已经在运行的程序
            //try
            //{
            //    _IoTServiceMonitor = MonitorIOT.GetInstance();
            //}
            //catch (Exception ex)
            //{
            //    SuperX.Common.Log.Logger.Warn(ex.ToString());
            //    SuperX.Common.Log.Logger.Trace(string.Format("检查运行时是否有在运行出现异常，直接返回"));
            //    return;
            //}

            //捕获未经处理的异常对象
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;

            Console.WriteLine("Starting HostedService...");
            InitLanguage();
            _HostedService = HostedService.Instance;
            HostedThread = new Thread(new ParameterizedThreadStart(Start)) { IsBackground = true };
            HostedThread.Start();
            _timer = new System.Timers.Timer { Interval = 5000 };
            _timer.Elapsed += _timer_Elapsed;
            _timer.Enabled = true;
            Console.CancelKeyPress += Console_CancelKeyPress;
            while (Console.ReadLine() != "q")
            {
            }
        }

        private static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e)
        {
            Stop();
        }

        private static void Stop()
        {
            if (Interlocked.CompareExchange(ref _stopped, 1, 0) == 1) return;

            Stopwatch sw = Stopwatch.StartNew();
            try
            {
                ProjService.GetInstance().Project.Stop();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
            Console.WriteLine(sw.ElapsedMilliseconds);
            ClosePress("Sentinel");
            Environment.Exit(0);
        }

        private static void _timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            if (_HostedService.IsRun)
            {
                Task.Factory.StartNew(() =>
                {
                    try
                    {
                        //Console.WriteLine(_HostedService.GetString());
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.ToString());
                    }
                });
            }
        }

        private static void Start(object obj)
        {
            _HostedService.Start();
        }

        private static void SetWorkDirectory()
        {
            dynamic type = (new Program()).GetType();
            string currentDirectory = Path.GetDirectoryName(type.Assembly.Location);
            System.IO.Directory.SetCurrentDirectory(currentDirectory);
        }

        private static void InitLanguage()
        {
            var supportedCultures = new Dictionary<string, CultureInfo> { { "zh-CN", new CultureInfo("zh-CN") } };
            foreach (var dir in Directory.GetDirectories(AppDomain.CurrentDomain.BaseDirectory))
            {
                try
                {
                    //see if this directory corresponds to a valid culture name
                    var dirinfo = new DirectoryInfo(dir);
                    var culture = CultureInfo.GetCultureInfo(dirinfo.Name);

                    //determine if a resources dll exists in this directory that matches the executable name
                    if (dirinfo.GetFiles("*.resources.dll").Length > 0)
                    {
                        supportedCultures.Add(dirinfo.Name, culture);
                    }
                }
                catch (ArgumentException) //ignore exceptions generated for any unrelated directories in the bin folder
                {
                }
            }
            var selectLanguage = "zh-CN";

            Thread.CurrentThread.CurrentCulture = supportedCultures[selectLanguage];
            Thread.CurrentThread.CurrentUICulture = supportedCultures[selectLanguage];
        }

        private static string _lastUnhandledException;
        private static DateTime _lastUnhandledExceptionDateTime = DateTime.MinValue;

        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            string errMsg = "抱歉, IoT系统运行错误,请及时联系专业人员....";
            try
            {
                lock (obj)
                {
                    string error = errMsg + Environment.NewLine + e.ExceptionObject;
                    if (Equals(error, _lastUnhandledException) && (DateTime.Now - _lastUnhandledExceptionDateTime).TotalSeconds < 2)
                    {
                        _lastUnhandledExceptionDateTime = DateTime.Now;
                    }
                    else
                    {
                        _lastUnhandledException = error;
                        _lastUnhandledExceptionDateTime = DateTime.Now;
                        SuperX.Common.Log.Logger.Error(error);
                    }
                }
            }
            catch (Exception ex)
            {
                lock (obj)
                {
                    string error = errMsg + Environment.NewLine + ex.StackTrace;
                    if (Equals(error, _lastUnhandledException) && (DateTime.Now - _lastUnhandledExceptionDateTime).TotalSeconds < 2)
                    {
                        _lastUnhandledExceptionDateTime = DateTime.Now;
                    }
                    else
                    {
                        _lastUnhandledException = error;
                        _lastUnhandledExceptionDateTime = DateTime.Now;
                        SuperX.Common.Log.Logger.Error(error);
                    }
                }
            }
            finally
            {
                //Current.Shutdown();
            }
        }

        private static string _lastUnobservedTaskException;
        private static DateTime _lastUnobservedTaskExceptionDateTime = DateTime.MinValue;

        private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            lock (obj)
            {
                var exceptionStrBuilder = new StringBuilder();
                var str = e.Exception.ToString();
                Exception ex = e.Exception;
                while (ex != null)
                {
                    exceptionStrBuilder.AppendLine(ex.Message);
                    exceptionStrBuilder.AppendLine(ex.StackTrace);
                    ex = ex.InnerException;
                }
                if (Equals(str, _lastUnobservedTaskException) && (DateTime.Now - _lastUnobservedTaskExceptionDateTime).TotalSeconds < 2)
                {
                    _lastUnobservedTaskExceptionDateTime = DateTime.Now;
                }
                else
                {
                    _lastUnobservedTaskExceptionDateTime = DateTime.Now;
                    _lastUnobservedTaskException = str;
                    SuperX.Common.Log.Logger.Warn(exceptionStrBuilder.ToString());
                }

                e.SetObserved();
            }
        }

        public static bool OpenPress(string FileName, string appName)
        {
            appName = appName.ToLower().Trim();
            if (Process.GetProcesses().Where(p => p.ProcessName.ToLower().Trim() == appName).ToArray().Any())
                return true;
            Process pro = new Process();
            if (System.IO.File.Exists(FileName))
            {
                pro.StartInfo.FileName = FileName;
                pro.Start();
                return true;
            }
            return false;
        }

        public static void ClosePress(string name)
        {
            name = name.ToLower().Trim();
            //获得任务管理器中的所有进程
            Process[] process = Process.GetProcesses().Where(p => p.ProcessName.ToLower().Trim() == name).ToArray();
            foreach (Process p in process)
            {
                try
                {
                    string processName = p.ProcessName.ToLower().Trim();
                    //判断是否包含阻碍更新的进程
                    if (processName == name)
                    {
                        p.Kill();
                    }
                }
                catch { }
            }
        }
    }
}